package com.xiaoyu.im

import android.util.Log
import com.netease.nimlib.sdk.msg.model.IMMessage
import `in`.srain.cube.util.log.LogEvent
import com.netease.nimlib.sdk.msg.model.CustomNotification
import com.xiaoyu.im.client.IMClient
import com.xiaoyu.im.datamodel.AppMessage
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.entity.ConversationEntity
import com.xiaoyu.im.log.IMLogClient
import org.joda.time.DateTime
import java.util.*

/**
 * See the document at "https://git.yizhoucp.cn/ops/serverless/issues/10#note_46990"
 */
const val EVENT_NAME_FOR_ERROR = "im-error"
const val EVENT_NAME_FOR_STREAM = "im-stream"

object IMLog {

    const val LOG_VERSION = 3

    @JvmStatic
    fun logSendError(message: AppMessage, type: String, code: Int, desc: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "send")
        logEvent.putData("type", type)
        logEvent.putData("code", code)
        logEvent.putData("desc", desc)
        logEvent.putData("sUid", UserData.getInstance().uid)
        logEvent.putData("rUid", message.chatToken.uid)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logFetchError(code: Int, desc: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "fetch_roam_messages")
        logEvent.putData("code", code)
        logEvent.putData("desc", desc)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logNetError(type: String, desc: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "fetch_info_from_server")
        logEvent.putData("type", type)
        logEvent.putData("desc", desc)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logLoginError(type: String, code: Int, desc: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "login")
        logEvent.putData("type", type)
        logEvent.putData("code", code)
        logEvent.putData("desc", desc)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logToAppMessageError(from: String, message: IMMessage?, e: Throwable) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "to_app_message")
        logEvent.putData("from", from)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("error", e.message ?: "")
        logEvent.putData("detail", Log.getStackTraceString(e))
        if (message != null) {
            val payloadString = if (message.attachment != null) message.attachment.toJson(false) else ""
            logEvent.putData("message_id", message.uuid)
            logEvent.putData("message_time", message.time)
            logEvent.putData("sUid", IMUtil.vendorCidToUid(message.fromAccount))
            logEvent.putData("rUid", IMUtil.vendorCidToUid(message.sessionId))
            logEvent.putData("message_payload", payloadString)
        }
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logNotificationToAppMessageError(from: String, notification: CustomNotification?, e: Throwable) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "notification_to_app_message")
        logEvent.putData("from", from)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("error", e.message ?: "")
        logEvent.putData("detail", Log.getStackTraceString(e))
        if (notification != null) {
            logEvent.putData("notification_time", notification.time)
            logEvent.putData("sUid", IMUtil.vendorCidToUid(notification.fromAccount))
            logEvent.putData("rUid", IMUtil.vendorCidToUid(notification.sessionId))
            logEvent.putData("notification_content", notification.content)
        }
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForObserveReceiveMessage(receiveType: String, senderUid: String, messageId: String, messageString: String, messageTime: Long) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "observe_receive_message")
        logEvent.putData("receive_type", receiveType)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("message", messageString)
        logEvent.putData("message_id", messageId)
        logEvent.putData("message_time", messageTime)
        logEvent.putData("message_date", DateTime(messageTime).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("sUid", senderUid)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("log_version", LOG_VERSION)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForFilterReceiveMessage(message: AppMessage, receiveType: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "filter_receive_message")
        logEvent.putData("receive_type", receiveType)
        logEvent.putData("send_offset", System.currentTimeMillis() - message.time)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("chat_id", message.chatToken.chatId)
        logEvent.putData("message_id", message.id)
        logEvent.putData("unique_key", message.payload.attrsCopy.optString("unique_key"))
        logEvent.putData("message_time", message.time)
        logEvent.putData("message_date", DateTime(message.time).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("text", message.payload.text)
        logEvent.putData("payload", message.payload)
        logEvent.putData("sUid", message.senderUid)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("invisible", message.invisible)
        logEvent.putData("log_version", LOG_VERSION)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImErrorForReceiveMessage(message: AppMessage) {
        val logEvent = LogEvent(EVENT_NAME_FOR_ERROR)
        logEvent.putData("op", "receive")
        logEvent.putData("send_offset", System.currentTimeMillis() - message.time)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("chat_id", message.chatToken.chatId)
        logEvent.putData("message_id", message.id)
        logEvent.putData("unique_key", message.payload.attrsCopy.optString("unique_key"))
        logEvent.putData("message_time", message.time)
        logEvent.putData("message_date", DateTime(message.time).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("text", message.payload.text)
        logEvent.putData("payload", message.payload)
        logEvent.putData("sUid", message.senderUid)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("invisible", message.invisible)
        logEvent.putData("log_version", LOG_VERSION)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForReceiveMessage(message: AppMessage, conversationType: String, conversationName: String) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "receive")
        logEvent.putData("send_offset", System.currentTimeMillis() - message.time)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("chat_id", message.chatToken.chatId)
        logEvent.putData("message_id", message.id)
        logEvent.putData("unique_key", message.payload.attrsCopy.optString("unique_key"))
        logEvent.putData("message_time", message.time)
        logEvent.putData("message_date", DateTime(message.time).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("text", message.payload.text)
        logEvent.putData("payload", message.payload)
        logEvent.putData("sUid", message.senderUid)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("invisible", message.invisible)
        logEvent.putData("log_version", LOG_VERSION)
        logEvent.putData("conversation_type", conversationType)
        logEvent.putData("conversation_name", conversationName)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForEnsureMessage(message: AppMessage) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "ensure_message")
        logEvent.putData("send_offset", System.currentTimeMillis() - message.time)
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("chat_id", message.chatToken.chatId)
        logEvent.putData("message_id", message.id)
        logEvent.putData("unique_key", message.payload.attrsCopy.optString("unique_key"))
        logEvent.putData("message_time", message.time)
        logEvent.putData("message_date", DateTime(message.time).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("text", message.payload.text)
        logEvent.putData("payload", message.payload)
        logEvent.putData("sUid", message.senderUid)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("invisible", message.invisible)
        logEvent.putData("log_version", LOG_VERSION)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForUpsertMessages(messages: List<AppMessage>, rowIds: List<Long>) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "upsert_message")
        logEvent.putData("messages", messages)
        logEvent.putData("message_count", messages.size)
        logEvent.putData("actual_count", rowIds.size)
        logEvent.putData("row_ids", rowIds)
        logEvent.putData("rUid", UserData.getInstance().uid)
        logEvent.putData("log_version", LOG_VERSION)
        IMLogClient.instance.addLog(logEvent)
    }

    @JvmStatic
    fun logImStreamForSend(message: AppMessage, conversation: ConversationEntity) {
        val logEvent = LogEvent(EVENT_NAME_FOR_STREAM)
        logEvent.putData("op", "send")
        logEvent.putData("vendor_type", IMClient.getInstance().vendorType)
        logEvent.putData("chat_id", conversation.chatId)
        logEvent.putData("message_id", message.id)
        logEvent.putData("unique_key", message.payload.attrsCopy.optString("unique_key"))
        logEvent.putData("message_time", message.time)
        logEvent.putData("message_date", DateTime(message.time).toString("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINESE))
        logEvent.putData("text", message.payload.text)
        logEvent.putData("payload", message.payload)
        logEvent.putData("sUid", message.senderUid)
        logEvent.putData("rUid", conversation.toUid)
        logEvent.putData("log_version", LOG_VERSION)
        logEvent.putData("conversation_type", conversation.type)
        IMLogClient.instance.addLog(logEvent)
    }
}

